#include "api.h"
#include "util.h"

Api* Api::m_instance;

Api::Api() {
    m_manager = new QNetworkAccessManager();
    configureHttps();
}

/**
 * @brief 发送HTTP请求的函数
 * @param Url 请求的相对URL路径
 * @param method HTTP方法(GET/POST/PUT/DELETE)
 * @param params 请求参数对象
 * @param timeoutMs 请求超时时间(毫秒)
 * @param callback 请求完成后的回调函数
 */
void Api::sendRequest(const QString& Url,
                 const QByteArray& method,
                 const QJsonObject& params,
                 int timeoutMs,
                 ApiCallback callback){
    // 构建完整URL
    QString urlStr = baseUrl+Url;
    QUrl url(urlStr);
    if (!url.isValid()) {
        // URL无效时直接返回错误
        if (callback) callback(false, {}, "无效的URL: " + urlStr, 404);
        return;
    }

    // 创建网络请求对象
    QNetworkRequest request(url);
    // 设置User-Agent头
    request.setHeader(QNetworkRequest::UserAgentHeader, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Qt/5.15.2");
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    // 添加身份令牌（如Authorization头）
    if (!m_globalToken.isEmpty()) {
        request.setRawHeader("Authorization", utf8Encode("Bearer " + m_globalToken));
    }

    // 所有方法都将参数拼接在URL上（URL?key=value&...格式）
    QUrlQuery query(url); // 解析URL中已有的查询参数（如果有）

    // 遍历参数，编码后添加到URL查询中（所有方法通用）
    for (auto it = params.begin(); it != params.end(); ++it) {
        QString key = it.key();
        QString value = it.value().toString();
        query.addQueryItem(key, urlEncode(value)); // URL编码参数值
    }

    // 更新URL（自动处理?和&符号）
    url.setQuery(query);
    request.setUrl(url);

    // 打印最终URL，验证参数是否正确拼接
    qDebug() << "最终请求URL:" << url.toString();

    // 发送请求（所有方法都使用URL参数，POST/PUT无需请求体）
    QNetworkReply* reply = nullptr;
    if (method == "GET") {
        reply = m_manager->get(request);
    } else if (method == "POST") {
        // POST方法也用URL参数，请求体为空
        reply = m_manager->post(request, QByteArray());
    } else if (method == "PUT") {
        // PUT方法也用URL参数，请求体为空
        reply = m_manager->put(request, QByteArray());
    } else if (method == "DELETE") {
        reply = m_manager->deleteResource(request);
    }

    // 创建超时定时器
    QTimer* timer = new QTimer(reply);
    timer->setSingleShot(true);
    // 连接超时信号
    QObject::connect(timer, &QTimer::timeout, [=]() {
        reply->abort();
        if (callback) callback(false, {}, "请求超时(" + QString::number(timeoutMs) + "ms)", -1);
    });
    timer->start(timeoutMs);

    // 连接响应完成信号
    QObject::connect(reply, &QNetworkReply::finished, [=]() {
        timer->stop();
        // 获取HTTP状态码
        int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        // 判断请求是否成功
        bool success = (reply->error() == QNetworkReply::NoError) && (statusCode >= 200 && statusCode < 300);
        QJsonObject responseObj;
        QString errorMsg;

        if (!success) {
            // 错误处理（包含HTTP状态码）
            errorMsg = QString("请求失败 [code=%1]: %2")
                           .arg(statusCode)
                           .arg(utf8Decode(reply->errorString().toUtf8()));
        } else {
            // 读取响应（强制UTF-8解码）
            QByteArray responseData = reply->readAll();
            QString responseStr = utf8Decode(responseData);  // 确保用UTF-8解析

            // 解析JSON
            QJsonParseError parseError;
            QJsonDocument jsonDoc = QJsonDocument::fromJson(
                utf8Encode(responseStr),  // 转为UTF-8字节数组再解析
                &parseError
                );
            if (parseError.error == QJsonParseError::NoError) {
                if (jsonDoc.isObject()) {
                    responseObj = jsonDoc.object();
                } else if (jsonDoc.isArray()) {
                    responseObj["data"] = jsonDoc.array();  // 数组包装为对象
                }
                errorMsg = "success";
            } else {
                success = false;
                errorMsg = "JSON解析失败: " + parseError.errorString() + "\n原始数据: " + responseStr;
            }
        }

        // 执行回调（传递结果）
        if (callback) {
            callback(success, responseObj, errorMsg, statusCode);
        }

        reply->deleteLater();
    });
}


Api* Api:: getInstance(){
    if (!m_instance) {
        m_instance = new Api();
    }
    return m_instance;
}

void Api::get(const QString& url, const QJsonObject& params, int timeout, ApiCallback callback){
    sendRequest(url,"GET",params,timeout,callback);
}
void Api::post(const QString& url, const QJsonObject& params, int timeout, ApiCallback callback){
    sendRequest(url,"POST",params,timeout,callback);
}
void Api::del(const QString& url, const QJsonObject& params, int timeout, ApiCallback callback){
    sendRequest(url,"DELETE",params,timeout,callback);
}
void Api::put(const QString& url, const QJsonObject& params, int timeout, ApiCallback callback){
    sendRequest(url,"PUT",params,timeout,callback);
}

/**
 * @brief 配置HTTPS加密连接
 * @param caCertPath CA证书文件路径，如果为空则不加载证书
 *
 * 该函数用于配置HTTPS加密连接，主要包括：
 * 1. 设置默认SSL配置
 * 2. 强制使用TLS 1.2或更高版本的协议
 * 3. 可选加载指定的CA证书文件
 * 4. 将配置设置为全局默认配置
 */
void Api::configureHttps(const QString& caCertPath){
    // 配置HTTPS加密
    QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();

    // 启用现代TLS协议（禁用不安全的SSLv3、TLSv1.0）
    sslConfig.setProtocol(QSsl::TlsV1_2OrLater);

    if(!caCertPath.isEmpty()) {
        QFile certFile(caCertPath);
        if(certFile.open(QIODevice::ReadOnly)){
            QSslCertificate cert(&certFile);
            if(!cert.isNull()){
                sslConfig.addCaCertificate(cert);
                qDebug() << "已加载CA证书：" << caCertPath;
            }
            certFile.close();
        }
    }

    QSslConfiguration::setDefaultConfiguration(sslConfig);
}






